package net.crozz.openapi.qq;

import com.google.gson.Gson;
import net.crozz.openapi.ApiException;
import net.crozz.openapi.http.Param;
import net.crozz.openapi.http.Requester;
import net.crozz.openapi.qq.model.Display;
import net.crozz.openapi.qq.model.Resp_me;
import net.crozz.openapi.qq.model.Resp_token;
import net.crozz.openapi.qq.model.Scope;
import org.apache.commons.lang.StringUtils;

public class QQ {
    private static final String BASE_URL = "https://graph.qq.com/";
    public final  User      user;
    public final  T         t;
    public final  Relation  relation;
    private final Requester client;
    private final String    client_id;
    private final String    client_secret;
    private final String    redirect_uri;

    public QQ(Requester client, String client_id, String client_secret, String redirect_uri) {
        this.client = client;
        this.client_id = client_id;
        this.client_secret = client_secret;
        this.redirect_uri = redirect_uri;

        this.user = new User(client, BASE_URL, client_id);
        this.t = new T(client, BASE_URL, client_id);
        this.relation = new Relation(client, BASE_URL, client_id);
    }

    /**
     * 获取Authorization Code<br/>
     * 从 {@link QQ} 获取 client_id, redirect_uri, 其余参数默认<br/>
     * 文档地址：http://wiki.connect.qq.com/使用authorization_code获取access_token
     *
     * @param state 必须，client端的状态值。用于第三方应用防止CSRF攻击，成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
     * @param scope 可选，请求用户授权时向用户显示的可进行授权的列表
     *
     * @see QQ#authorize(String, String, String, Scope[], Display, String, Boolean)
     */
    public String authorize(String state, Scope[] scope) {
        return authorize(client_id, redirect_uri, state, scope, Display.DEFAULT, null, false);
    }

    /**
     * 获取Authorization Code<br/>
     * 文档地址：http://wiki.connect.qq.com/使用authorization_code获取access_token
     *
     * @param client_id    必须，申请QQ登录成功后，分配给应用的appid。
     * @param redirect_uri 必须，成功授权后的回调地址，必须是注册appid时填写的主域名下的地址，建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
     * @param state        必须，client端的状态值。用于第三方应用防止CSRF攻击，成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
     * @param scope        可选，请求用户授权时向用户显示的可进行授权的列表
     * @param display      可选，仅PC网站接入时使用。用于展示的样式。不传则默认展示为PC下的样式。如果传入“mobile”，则展示为mobile端下的样式。
     * @param gut          仅WAP网站接入时使用。QQ登录页面版本（1：wml版本； 2：xhtml版本），默认值为1。
     * @param wap          是否使wap版，默认为false
     */
    public String authorize(
            String client_id, String redirect_uri, String state,
            Scope[] scope, Display display, String gut, Boolean wap
    ) {
        String scopeStr = "";
        if (scope != null) {
            scopeStr = StringUtils.join(scope, ",");
        }

        String url = "https://graph.qq.com/oauth2.0/authorize";
        if (Boolean.TRUE.equals(wap)) {
            url = "https://graph.z.qq.com/moc2/authorize";
        }
        return Requester.makeUrl(
                url,
                Param.newParam("client_id", client_id),
                Param.newParam("redirect_uri", redirect_uri),
                Param.newParam("response_type", "code"),
                Param.newParam("state", state),
                Param.newParam("scope", scopeStr),
                Param.newParam("display", display),
                Param.newParam("gut", gut)
        );
    }

    /**
     * 通过Authorization Code获取Access Token<br/>
     * 权限自动续期<br/>
     * 文档地址：http://wiki.connect.qq.com/使用authorization_code获取access_token<br/>
     * Step2：通过Authorization Code获取Access Token<br/>
     * Step3：（可选）权限自动续期，获取Access Token<br/>
     * 从 {@link QQ} 获取 client_id, redirect_uri, redirect_uri其余参数默认
     *
     * @param grant_type    授权类型，“authorization_code”或“refresh_token”。
     * @param code          上一步返回的authorization code。如果用户成功登录并授权，则会跳转到指定的回调地址，并在URL中带上Authorization
     *                      Code。注意此code会在10分钟内过期。
     * @param refresh_token {@link Resp_token}中的refresToken。
     *
     * @see QQ#token(String, String, String, String, String, String, Boolean)
     */
    public Resp_token token(String grant_type, String code, String refresh_token) throws ApiException {
        return token(client_id, client_secret, grant_type, code, refresh_token, redirect_uri, false);
    }

    /**
     * 通过Authorization Code获取Access Token<br/>
     * 权限自动续期<br/>
     * 文档地址：http://wiki.connect.qq.com/使用authorization_code获取access_token<br/>
     * Step2：通过Authorization Code获取Access Token<br/>
     * Step3：（可选）权限自动续期，获取Access Token<br/>
     *
     * @param client_id     申请QQ登录成功后，分配给网站的appid。
     * @param client_secret 申请QQ登录成功后，分配给网站的appkey。
     * @param grant_type    授权类型，“authorization_code”或“refresh_token”。
     * @param code          上一步返回的authorization code。如果用户成功登录并授权，则会跳转到指定的回调地址，并在URL中带上Authorization
     *                      Code。注意此code会在10分钟内过期。
     * @param refresh_token {@link Resp_token}中的refresToken。
     * @param redirect_uri  与上面一步中传入的redirect_uri保持一致。
     * @param wap           是否使wap版，默认为false
     */
    public Resp_token token(
            String client_id, String client_secret, String grant_type,
            String code, String refresh_token, String redirect_uri, Boolean wap
    ) throws ApiException {
        String url = "https://graph.qq.com/oauth2.0/token";
        if (Boolean.TRUE.equals(wap)) {
            url = "https://graph.z.qq.com/moc2/token";
        }
        return client.getObj(
                Resp_token.class,
                url,
                Param.newParam("client_id", client_id),
                Param.newParam("client_secret", client_secret),
                Param.newParam("grant_type", grant_type),
                Param.newParam("code", code),
                Param.newParam("refresh_token", refresh_token),
                Param.newParam("redirect_uri", redirect_uri)
        );
    }


    /**
     * 获取用户OpenID<br/>
     * 文档地址：http://wiki.connect.qq.com/获取用户openid_oauth2-0
     *
     * @param access_token 授权令牌
     * @param wap          是否使wap网站访问
     */
    // TODO
    public Resp_me me(String access_token, Boolean wap) throws ApiException {
        String url = "https://graph.qq.com/oauth2.0/me";
        if (Boolean.TRUE.equals(wap)) {
            url = "https://graph.z.qq.com/moc2/me";
        }
        String result = client.getStr(url, Param.newParam("access_token", access_token)).trim();
        if (result.startsWith("callback")) {// PC网站的正确返回结果
            return new Gson().fromJson(result.substring(result.indexOf("{"), result.lastIndexOf("}") + 1), Resp_me.class);
        } else {// WAP网站返回结果或错误信息
            // TODO
            return null;
        }
    }
}